- Java线程死锁是由于有些资源彼此交叉取用,就有可能造成死结.
- 如1线程中 取得A对象的锁定后又要取得B对象的锁定.但是同时2线程中取得B对象的锁定后又要取得A对象的锁定.这两个线程同时发生时就会造成,1线程拿到A对象锁定后等待B对象的锁定.2线程拿到B对象锁定后等待A对象锁定.这样就会进入没有停止的等待中.
- 线程死锁的一个简单例子:
- package deadLockThread;
- public class Test {
- private int size=0;
- public synchronized void doSome(){
- size++;
- }
- public synchronized void doTest(Test test){
- try {
- Thread.sleep(1000);//睡眠1秒 效果更明显
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- test.doSome(); //另外一个对象调用synchronized 函数 需要取得该对象的对象锁定
- }
- }
- package deadLockThread;
- public class DeadLock {
- public static void main(String[] args) {
- final Test t1=new Test();
- final Test t2=new Test();
- Thread th1=new Thread(new Runnable() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- t1.doTest(t2);
- }
- });
- Thread th2=new Thread(new Runnable() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- t2.doTest(t1);
- }
- });
- th1.start();
- th2.start();
- }
- }
- 如果真的没办法避免资源的交叉取用 我的解决方法是使用并行API在取得第一个对象锁定前先检测另外一个对象的对象锁定有没有被其他的线程拿走了.
- synchronized 要求线程必须取得对象锁定,才可以执行所标识的区块范围.然而使用synchronized 有许多的限制,未取得锁定的线程会直接被打断.所以我这里使用并行API Lock 替代直接操作synchronized .
- package deadLockThread;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class Test {
- private int size = 0;
- private Lock lock = new ReentrantLock();
- public void doSome() {
- System.out.println(Thread.currentThread().getName() + "获取size");
- size++;
- }
- public void doTest(Test test) {
- while (true) {
- boolean myLock = this.lock.tryLock();// 尝试取得当前对象的Lock锁定
- boolean testLock = test.lock.tryLock();// 尝试取得被传入得对象的Lock锁定
- try {
- if (myLock && testLock) { //当两个对象的Lock 都获取到后再进行 操作
- test.doSome();
- break;
- }
- } finally {
- if (myLock) {
- this.lock.unlock();
- }
- if (testLock) {
- test.lock.unlock();
- }
- }
- }
- }
- }
- package deadLockThread;
- public class DeadLock {
- public static void main(String[] args) {
- final Test t1 = new Test();
- final Test t2 = new Test();
- Thread th1 = new Thread(new Runnable() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- t1.doTest(t2);
- }
- });
- Thread th2 = new Thread(new Runnable() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- t2.doTest(t1);
- }
- });
- th1.start();
- th2.start();
- }
- }